﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using FootSteps.Data;

namespace FootSteps.Domain.Loggers.Proccess
{
    public class OpenProcessArgs
    {
        public Process Process { get; private set; }
        public DateTime Time { get; private set; }
        public ProcessState State { get; private set; }

        public string ProcessName
        {
            get
            {
                return (GetPropertyLastKnowValue(e => e.ProcessName, Process) ?? "").ToString();
            }
        }

        public OpenProcessArgs(Process process, DateTime time, ProcessState state)
        {
            Process = process;
            Time = time;
            State = state;

        }

        public override string ToString()
        {
            return string.Format("[at {0}]: (Process {1}) -> {2} [{3}][{4}]", Time, State,
                GetPropertyLastKnowValue(x => x.ProcessName, Process),
                Process.MainWindowTitle, GetPropertyLastKnowValue(x=> x.MainModule.FileName, Process));
        }

        private static Dictionary<Process, Dictionary<PropertyInfo, object>> _lastKnowProcessValues = new Dictionary<Process, Dictionary<PropertyInfo, object>>();
        
        private static object GetPropertyLastKnowValue<TValue>(Expression<Func<Process, TValue>> propertySelector, Process process)
        {
            if (!(propertySelector.Body is MemberExpression)
                || !((((MemberExpression)propertySelector.Body).Member) is PropertyInfo))
                throw new Exception("Expressaon Invalida");

            if (!_lastKnowProcessValues.ContainsKey(process)) _lastKnowProcessValues[process] = new Dictionary<PropertyInfo, object>();

            var member = (PropertyInfo)((MemberExpression) propertySelector.Body).Member;
            object value;
            try
            {
                value = member.GetValue(process);
            }
            catch (Exception)
            {
                if (_lastKnowProcessValues[process].ContainsKey(member))
                    return _lastKnowProcessValues[process][member];
                value = "";
            }

            return _lastKnowProcessValues[process][member] = value;
        }
        
    }

   
}